package cc.mrbird.febs.accounting.service.impl;

import cc.mrbird.febs.accounting.dto.company.CompanyDTO;
import cc.mrbird.febs.accounting.dto.project.ProjectInfoDTO;
import cc.mrbird.febs.accounting.entity.*;
import cc.mrbird.febs.accounting.mapper.*;
import cc.mrbird.febs.accounting.service.ICompanyService;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.accounting.service.IProjectService;
import cc.mrbird.febs.common.entity.Strings;
import cc.mrbird.febs.common.utils.FebsUtil;
import cc.mrbird.febs.system.entity.Role;
import cc.mrbird.febs.system.mapper.RoleMapper;
import cc.mrbird.febs.system.service.impl.RoleServiceImpl;
import cc.mrbird.febs.utils.CodeConstant;
import cc.mrbird.febs.utils.PermissionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import org.apache.catalina.filters.RemoteIpFilter;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.C;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.annotation.Propagation;
import lombok.RequiredArgsConstructor;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 *  Service实现
 *
 * @author baoyinlei
 * @date 2021-09-28 23:26:45
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    @Resource
    private final ProjectMapper projectMapper;
    @Resource
    private CompanyMapper companyMapper;
    @Resource
    private ProjectTypeMapper projectTypeMapper;
    @Resource
    private DetailCostMapper detailCostMapper;
    @Resource
    private StandardSubExtraMapper standardSubExtraMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RoleServiceImpl roleService;
    @Resource
    private CompanyProjectMapper companyProjectMapper;
    @Resource
    private CompanyProjectServiceImpl companyProjectService;

    @Override
    public IPage<Project> queryProjects(QueryRequest request, Project project) {
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        if (Objects.nonNull(project) && StringUtils.isNotBlank(project.getProjectName())) {
            queryWrapper.like(Project::getProjectName, project.getProjectName());
        }
        queryWrapper.eq(Project::getIsDeleted, 0);
        queryWrapper.orderByDesc(Project::getId);
        Page<Project> page = this.page(new Page<>(request.getPageNum(), request.getPageSize()), queryWrapper);
        List<Project> records = page.getRecords();
        records.forEach(e -> {
            Company company = companyMapper.selectById(e.getCompanyId());
            ProjectType projectType =projectTypeMapper.selectById(e.getProjectTypeId());
            e.setCompanyName(company.getCompanyName());
            e.setProjectType(projectType.getProjectType());
        });
        return page;
    }

    @Override
    public List<Project> findProjects(Project project) {
	    LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getIsDeleted, 0);
        queryWrapper.orderByDesc(Project::getId);
        boolean flag = FebsUtil.getCurrentUser().getUserId().equals(CodeConstant.specialUserId);
        if(!flag && project != null && project.getNeedPermission() != null && project.getNeedPermission())   // 需要根据公司权限
        {
            List<String> perList = new ArrayList<>();
            perList.add("-1");
            List<CompanyDTO> companyDTOS = roleService.getCompanyProjectByUserId();
            for (CompanyDTO companyDTO : companyDTOS) {
                for (ProjectInfoDTO projectInfo : companyDTO.getProjectInfos()) {
                    perList.add(projectInfo.getProjectId().toString());
                }
            }
            queryWrapper.in(Project::getId, perList);
        }
        List<Project> list = this.baseMapper.selectList(queryWrapper);

        if (project != null && project.getNeedCost() != null && project.getNeedCost()) {
            List<String> ids = new ArrayList<>();
            list.forEach(e->ids.add(e.getId().toString()));
            LambdaQueryWrapper<DetailCost> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.like(DetailCost::getYearMonth, project.getYear());
            queryWrapper1.in(DetailCost::getProjectId, ids);
            List<DetailCost> detailCosts = detailCostMapper.selectList(queryWrapper1);
            Set<String> hasCostId = new HashSet<>();
            detailCosts.forEach(e->hasCostId.add(e.getProjectId().toString()));
            list = list.stream().filter(e->hasCostId.contains(e.getId().toString())).collect(Collectors.toList());
        }
		return list;
    }

    @Override
    public List<Project> findOngoingProjects() {
        return this.projectMapper.queryOngoingProject();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean createProject(Project project) {
        project.setProjectCode(UUID.randomUUID().toString());
        project.setCreateBy(FebsUtil.getCurrentUser().getUsername());
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getIsDeleted, 0);
        List<Project> projects = this.getBaseMapper().selectList(queryWrapper);
        Set<String> projectNames = new HashSet<>();
        for (Project e : projects) {
            projectNames.add(e.getProjectName().trim());
        }
        if (!projectNames.contains(project.getProjectName().trim())) {
            this.save(project);
            LambdaQueryWrapper<Project> q = new LambdaQueryWrapper<>();
            q.eq(Project::getIsDeleted, 0);
            q.eq(Project::getProjectName, project.getProjectName().trim());
            Project newProject = this.getBaseMapper().selectOne(q);

            List<CompanyProject> companyProjects = new ArrayList<>();
            // 先添加项目公司关系
            String[] cidList = project.getCompanyId().split(",");
            for (String cid : cidList) {
                CompanyProject companyProject = new CompanyProject();
                companyProject.setProjectId(newProject.getId());
                companyProject.setCompanyId(Long.parseLong(cid));
                companyProject.setCreateBy(FebsUtil.getCurrentUser().getUsername());
                companyProjects.add(companyProject);
            }
            companyProjectService.saveBatch(companyProjects);
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateProject(Project project) {
        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Project::getIsDeleted, 0);
        List<Project> projects = this.getBaseMapper().selectList(wrapper);
        Set<String> projectNames = new HashSet<>();
        for (Project e : projects) {
            if (!e.getId().equals(project.getId())) {
                projectNames.add(e.getProjectName().trim());
            }
        }
        if (!projectNames.contains(project.getProjectName().trim())) {
            if (project.getManualTax() == 0) {
                detailCostMapper.deleteTaxRecord(project.getId());
            }
            // 删除项目公司关系
            LambdaQueryWrapper<CompanyProject> del = new LambdaQueryWrapper<>();
            del.eq(CompanyProject::getProjectId, project.getId());
            companyProjectMapper.delete(del);
            // 添加项目公司关系
            List<CompanyProject> companyProjects = new ArrayList<>();
            String[] cidList = project.getCompanyId().split(",");
            for (String cid : cidList) {
                CompanyProject companyProject = new CompanyProject();
                companyProject.setProjectId(project.getId());
                companyProject.setCompanyId(Long.parseLong(cid));
                companyProject.setCreateBy(FebsUtil.getCurrentUser().getUsername());
                companyProjects.add(companyProject);
            }
            companyProjectService.saveBatch(companyProjects);

            project.setModifyTime(new Date());
            project.setModifyBy(FebsUtil.getCurrentUser().getUsername());
            this.saveOrUpdate(project);
            return true;
        } else {
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProject(String projectIds) {
        List<String> list = Arrays.asList(projectIds.split(Strings.COMMA));
        list.forEach(e -> {
            Project project = new Project();
            project.setId(Long.parseLong(e));
            project.setIsDeleted(1);
            project.setModifyBy(FebsUtil.getCurrentUser().getUsername());
            project.setModifyTime(new Date());
            this.baseMapper.updateById(project);
        });
        // 删除公司关系
        LambdaQueryWrapper<CompanyProject> del = new LambdaQueryWrapper<>();
        del.in(CompanyProject::getProjectId, list);
        companyProjectMapper.delete(del);
        // 删除对应费用
        this.detailCostMapper.deleteByProjectId(list);
        this.standardSubExtraMapper.deleteByProjectId(list);
	}

    @Override
    public List<Project> getProjectByCompanyId(Long companyId) {
        if (Objects.isNull(companyId)) {
            return null;
        }
        LambdaQueryWrapper<CompanyProject> q = new LambdaQueryWrapper<>();
        q.eq(CompanyProject::getCompanyId, companyId);
        List<CompanyProject> projects = companyProjectMapper.selectList(q);
        List<Long> projectIds = new ArrayList<>();
        projects.forEach(cp -> projectIds.add(cp.getProjectId()));

        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Project::getId, projectIds);
        queryWrapper.eq(Project::getIsDeleted, 0);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public Project getProjectById(Long projectId) {
        return this.baseMapper.selectById(projectId);
    }

    @Override
    public List<Project> getProjectByIds(List<String> projectIds) {
        LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Project::getIsDeleted, 0);
        queryWrapper.in(Project::getId, projectIds);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public void updateProjectComment(Long projectId, String comment) {
        this.baseMapper.updateProjectCommentById(projectId, comment);
    }

    @Override
    public void updateProjectComment2(Long projectId, String comment) {
        Project project = this.baseMapper.selectById(projectId);
        project.setComment2(comment);
        this.baseMapper.updateById(project);
    }
}
